/**
 * =================================================================
 * 版权所有 2011-2013 深圳市泰海网络科技服务有限公司，并保留所有权利
 * -----------------------------------------------------------------
 * 这不是一个自由软件！您不能在任何未经允许的前提下对程序代码进行修改和使用；
 * 不允许对程序代码以任何形式任何目的的再发布
 * =================================================================
 */
package com.imoney.paymgr.web.exception;

import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.async.WebAsyncUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;

import com.imoney.framework.base.exception.ServiceException;
import com.imoney.framework.base.utils.StringUtils;
import com.imoney.paymgr.web.utils.JsonMessage;
import com.imoney.paymgr.web.utils.WebUtil;

/**
 * 类说明：<br>
 * 
 * <p>
 * 详细描述：<br>
 * 
 * </p>
 * 
 * <pre>
 * ——————————————————————————————————————————————————————————————————
 * |		修改人		|		修改时间			|		修改原因
 * ——————————————————————————————————————————————————————————————————
 * |	zengxx 曾宪新	|		2013-3-27		|	
 * ——————————————————————————————————————————————————————————————————
 * </pre>
 * 
 * @author zengxx 曾宪新(Xavier.zeng)
 * 
 *         CreateDate: 2013-3-27
 */
public class DefaultPayHandlerExceptionResolver extends
		DefaultHandlerExceptionResolver {

	private static Logger log = LoggerFactory
			.getLogger(DefaultPayHandlerExceptionResolver.class);

	/**
	 * 默认的异常信息
	 */
	private static final String DEFAULT_ERROR_MSG = "网络异常，请刷新重试！";

	/**
	 * 默认的异常状态码
	 */
	private static final String DEFAULT_ERROR_STATUS_CODE = "500";

	/**
	 * session无效状态码
	 */
	private static final String SESSION_INVALID_STATUS_CODE = "510";

	/**
	 * session无效code
	 */
	public static final String SESSION_INVALID_CODE = "session_invalid";

	/**
	 * session无效MSG
	 */
	private static final String SESSION_INVALID_MSG = "session无效";

	/**
	 * 默认的异常提示页
	 */
	private String defaultErrorView;

	/**
	 * 信息源
	 */
	private MessageSource messageSource;

	@Override
	protected ModelAndView doResolveException(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex) {
		WebRequest webRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
		boolean isAjax = WebUtil.isAjaxRequest(webRequest);
		if (isAjax) {
			return doResolveJsonException(request, response, handler, ex);
		}

		String msg = DEFAULT_ERROR_MSG;
		if (ex instanceof ServiceException) {
			ServiceException sex = (ServiceException) ex;
			if (StringUtils.isNotEmpty(sex.getCode())) {
				try {
					String[] codes = sex.getCode().split("#");
					msg = messageSource.getMessage(codes[0],
							getMessageArgs(codes), Locale.SIMPLIFIED_CHINESE);
				} catch (NoSuchMessageException e) {
					log.warn("errorCode=[" + sex.getCode() + "]没有对应的MSG配置");
					if (StringUtils.isNotEmpty(sex.getMsg())) {
						msg = sex.getMsg();
					} else {
						log.error("请求发生未知异常", ex);
					}
				}
			}
			else if (StringUtils.isNotEmpty(sex.getMsg())) {
				msg = sex.getMsg();
			}
			request.setAttribute("msg", msg);
		}
		// 首先使用原生的默认解析，不能解析则直接默认解析
		ModelAndView modelAndView = super.doResolveException(request, response,
				handler, ex);
		if (null != modelAndView) {
			return modelAndView;
		}

		return doDefaultResolve(request, response, handler, ex);
	}

	/**
	 * JSON请求异常解析
	 * 
	 * @param request
	 * @param response
	 * @param handler
	 * @param ex
	 * @return
	 */
	protected ModelAndView doResolveJsonException(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex) {
		response.setContentType("application/json;charset=UTF-8");
		String msg = DEFAULT_ERROR_MSG;
		String statusCode = DEFAULT_ERROR_STATUS_CODE;
		try {
			if (ex instanceof ServiceException) {
				ServiceException sex = (ServiceException) ex;
				// 如果已有错误信息，则取错误信息
				if (SESSION_INVALID_CODE.equals(sex.getCode())) {
					statusCode = SESSION_INVALID_STATUS_CODE;
					msg = SESSION_INVALID_MSG;
				} 
				else if (StringUtils.isNotEmpty(sex.getCode())) {
					try {
						String[] codes = sex.getCode().split("#");
						msg = messageSource.getMessage(codes[0],
								getMessageArgs(codes), Locale.SIMPLIFIED_CHINESE);
					} catch (NoSuchMessageException e) {
						log.warn("errorCode=[" + sex.getCode() + "]没有对应的MSG配置");
						if (StringUtils.isNotEmpty(sex.getMsg())) {
							msg = sex.getMsg();
						} else {
							log.error("请求发生未知异常", ex);
						}
					}
				}
			} else {
				log.error("JSON请求发生未知异常", ex);
			}

			JsonMessage jms = new JsonMessage("error", statusCode, msg);
			response.getWriter().print(jms);
		} catch (Exception e) {
			// JSON类的处理异常，交给容器处理
			throw new RuntimeException("处理JSON异常解析异常", e);
		}

		return new ModelAndView();
	}

	/**
	 * 方法说明：默认的错误解析<br>
	 * 
	 * @param request
	 * @param response
	 * @param handler
	 * @param ex
	 * @return
	 */
	protected ModelAndView doDefaultResolve(HttpServletRequest request,
			HttpServletResponse response, Object handler, Exception ex) {
		log.error("发生未知异常，默认返回500错误", ex);

		/**
		 * 做审记日志，记录入数据库
		 */

		return new ModelAndView(defaultErrorView);
	}

	public String getDefaultErrorView() {
		return defaultErrorView;
	}

	public void setDefaultErrorView(String defaultErrorView) {
		this.defaultErrorView = defaultErrorView;
	}

	public void setMessageSource(MessageSource messageSource) {
		this.messageSource = messageSource;
	}
	
	/**
	 * 从异常code字符串中， 获取Message的动态参数 规则:如果需要需要动态绑定消息参数，请在异常code后加上#号分隔符,
	 * 再加上动态参数内容，如果多个参数用,号分隔 例:member-mobile-invalid#13800138000,13800138001
	 * 
	 * @param codes
	 * @return
	 */
	private String[] getMessageArgs(String[] codes) {
		String[] args = null;
		if (codes.length > 1) {
			args = codes[1].split(",");
		}

		return args;
	}
}
